#!/usr/bin/perl -w

use strict;
use File::Basename;
use lib dirname($0) . '/lib';
use RBM;
use YAML::XS;
use Getopt::Long;
#use Data::Dump qw/dd/;

my %actions = (
    projects => {
        run   => \&print_projects,
        descr => 'Print projects list',
    },
    fetch => {
        run => \&fetch,
        descr => 'Fetch commits from remote git repository',
    },
    tar  => {
        run   => \&tar,
        descr => 'Create source tarball',
    },
    rpmspec => {
        run => \&rpmspec,
        descr => 'Create rpm spec file',
    },
    rpm => {
        run => sub { build_script('rpm', @_) },
        descr => 'Build an rpm package',
    },
    srpm => {
        run => sub { build_script('srpm', @_) },
        descr => 'Create source rpm file',
    },
    'deb-src' => {
        run => sub { build_script('deb_src', @_) },
        descr => 'Create debian source package',
    },
    'deb' => {
        run => sub { build_script('deb', @_) },
        descr => 'Create debian package',
    },
    build => {
        run => sub { build_script('build', @_) },
        descr => 'Build project with a custom build script',
    },
    pkg => {
        run => \&pkg,
        descr => 'Build a package',
    },
    publish => {
        run => \&publish,
        descr => 'Publish a package',
    },
    showconf => {
        run => \&show_conf,
        descr => 'Show configuration',
    },
    usage => {
        run => \&usage,
        descr => 'Show usage information for an action',
        no_config => 1,
    },
    '--help' => {
        run => \&usage,
        no_config => 1,
    },
);

sub usage {
    if ($_[1] && $actions{$_[1]} && $actions{$_[1]}->{descr}) {
        system('man', "rbm-$_[1]");
    } else {
        print STDERR "$0 <action> [options]\n";
        print STDERR "$0 usage [action]\n\n";
        print STDERR "Available actions:\n";
        my @actions = grep { $actions{$_}->{descr} } keys %actions;
        print STDERR map { " - $_ : $actions{$_}->{descr}\n" } @actions;
        print STDERR "\nSee '$0 usage <action>' for usage informations\n";
    }
    exit 0;
}
sub usageexit {
    my $cmd = shift;
    print STDERR "Incorrect argument(s).\n";
    print STDERR "See '$0 usage $cmd' for usage informations\n";
    exit 1;
}

sub set_options {
    my @options = qw(distribution=s version=s tag-gpg-id=s@ commit-gpg-id=s@
                     projects-dir=s git-clone-dir=s git-hash=s output-dir=s
                     compress_tar=s pkg-rel=s timestamp=i fetch!
                     gpg-keyring=s gpg-keyring-dir=s gpg-args=s gpg-bin=s
                     sysconf-file=s debsign-keyid=s use-pbuilder!
                     step=s target=s@ publish-src-dir=s debug! hg-clone-dir=s
                     hg-hash=s localconf-file=s build-log=s);
    my %val;
    Getopt::Long::GetOptionsFromArray(\@_, \%val, @options) || exit 1;
    foreach my $k (keys %val) {
        if ($k eq 'step') {
            $RBM::config->{step} = $val{$k};
            next;
        }
        my $l = $k;
        $l =~ s/-/_/g;
        $RBM::config->{run}{$l} = $val{$k};
    }
    RBM::load_system_config(@_);
    RBM::load_local_config(@_);
    return $RBM::config->{run}{args} = \@_;
}

sub show_conf {
    shift;
    my $args = set_options(@_);
    if (@$args == 0) {
        print YAML::XS::Dump($RBM::config);
        return;
    }
    my $project = shift @$args;
    RBM::valid_project($project);
    my $r = @$args ? RBM::project_config($project,
                        @$args == 1 ? $args->[0] : \@$args)
                : $RBM::config->{projects}{$project};
    RBM::exit_error "Undefined" unless defined $r;
    print ref $r ? YAML::XS::Dump($r) : "$r\n";
}

sub fetch {
    shift;
    $RBM::config->{run}{fetch} = 1;
    my $args = set_options(@_);
    my @l = @$args ? @$args : (RBM::projectslist());
    foreach my $project (@l) {
        RBM::valid_project($project);
        if (RBM::project_config($project, 'git_url')) {
            print "Fetching commits for $project\n";
            RBM::git_clone_fetch_chdir($project);
        } elsif (RBM::project_config($project, 'hg_url')) {
            print "Fetching commits for $project\n";
            RBM::hg_clone_fetch_chdir($project);
        } else {
            print "Skipping $project\n";
        }
    }
}

sub tar {
    usageexit($_[0]) unless @_ >= 2;
    shift;
    my $args = set_options(@_);
    usageexit('tar') unless @$args == 1;
    RBM::maketar($args->[0]);
}

sub rpmspec {
    usageexit($_[0]) unless @_ >= 2;
    shift;
    my $args = set_options(@_);
    usageexit('rpmspec') unless @$args == 1;
    RBM::rpmspec($args->[0]);
}

sub print_projects {
    usageexit($_[0]) unless @_ == 1;
    print join("\n", RBM::projectslist()), "\n";
}

sub build_script {
    my $script_name = shift;
    usageexit($_[0]) unless @_ >= 2;
    my $cmd = shift;
    my $args = set_options(@_);
    usageexit($cmd) unless @$args == 1;
    $script_name = $RBM::config->{step} if $RBM::config->{step} ne 'rbm_init';
    RBM::build_pkg($args->[0], { pkg_type => $script_name });
}

sub pkg {
    usageexit($_[0]) unless @_ >= 2;
    my $cmd = shift;
    my $args = set_options(@_);
    usageexit($cmd) unless @$args == 1;
    RBM::build_pkg($args->[0]);
}

sub publish {
    usageexit($_[0]) unless @_ >= 2;
    my $cmd = shift;
    my $args = set_options(@_);
    usageexit($cmd) unless @$args == 1;
    RBM::publish($args->[0]);
}

if (@ARGV == 0 || !$actions{$ARGV[0]}) {
    usage();
    exit 1;
}
usage('usage', $ARGV[0]) if grep { $_ eq '--help' } @ARGV[1..(@ARGV - 1)];
RBM::load_config unless $actions{$ARGV[0]}->{no_config};
RBM::set_default_env unless $actions{$ARGV[0]}->{no_config};
$actions{$ARGV[0]}->{run}->(@ARGV);

# vim: expandtab sw=4
